package com.jy.api.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.opensearch.util.URLEncoder;
import com.jy.api.dao.*;
import com.jy.api.domain.*;
import com.jy.api.enums.OrderPayChannel;
import com.jy.api.enums.PayTypeEnum;
import com.jy.api.httputil.Constant;
import com.jy.api.httputil.HttpClient;
import com.jy.api.httputil.SignUtil;
import com.jy.api.payReq.*;
import com.jy.api.payRes.*;
import com.jy.api.service.StorePayService;
import com.jy.api.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class HuiFuServiceImpl implements StorePayService {


    @Autowired
    private AliyunMNSSend aliyunMNSSend;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private PaymentDao paymentDao;
    @Autowired
    private TransactionTemplate transactoinTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RewardDao rewardDao;
    @Autowired
    private StoreDao storeDao;
    @Autowired
    private RedisSyncLocker redisSyncLocker;
    @Autowired
    private AccountBalanceDao accountBalanceDao;
    @Autowired
    private StorePayDao storePayDao;
    @Value("${api.gateway.url}")
    private String baseURL;
    @Autowired
    private PaymentServiceImpl service;


    public AllPayBaseResult finalHuiFuPay(Order order, String authCode, StorePay storePay, Store store) throws Exception {
        AllPayBaseResult result = huifuPay(order, authCode, storePay);
        log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{},订单内容{}", order.getStoreId(), order.getId(), "支付开始", result, order);
        log.info("payResult" + result);
        order.setPayChannel(OrderPayChannel.HUI_FU);
        if (result.isSuccess()) {
            // 支付成功，更新订单状态
            Payment payment = service.createPaymentBySwiftPassResult(result, storePay.getStoreId());
            if (OrderSource.POS == order.getSource()) {
                order.setStatus(OrderStatus.FINISHED);
            } else {
                order.setStatus(OrderStatus.UNFINISHED);
            }
            order.setPaymentTime(payment.getCreateTime());
            order.setPayId(payment.getId());
            order.setChannel(result.getTradeType());
            log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{}", order.getStoreId(), order.getId(), "支付成功", result);
            orderDao.save(order);
            paymentDao.save(payment);
            service.postPaymentSuccess(order, store);
        } else if (result.isFailed()) {
            // 支付失败，允许订单再次支付
            order.setStatus(OrderStatus.CANCELED);
            orderDao.save(order);
        } else {
            // 支付结果不确定
            order.setStatus(OrderStatus.NOTSURE);
            orderDao.save(order);
            log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{}", order.getStoreId(), order.getId(), "支付结果不确定", result);
            aliyunMNSSend.sendClint(order.getId());
        }
        redisTemplate.opsForValue().set(order.getId(), order.getId(), 5, TimeUnit.SECONDS);
        return result;
    }


    public AllPayBaseResult huifuPay(Order order, String authCode, StorePay storePay) throws Exception {
        HuiFuMicroPayReq huiFuMicroPayReq = new HuiFuMicroPayReq(order, authCode, storePay.getMchId());
        AllPayBaseResult result = new AllPayBaseResult();
        huiFuMicroPayReq.setGoodsDesc(URLEncoder.encodeUTF8(service.getBody(order)));
        String jsonData = dealHuiFuMicroPay(huiFuMicroPayReq);
        String checkValue = SignUtil.getInstance().signByCFCA(jsonData);
        String traceNo = UUID.randomUUID().toString().replaceAll("-", "");
        String resultStr = HttpClient.getInstance().send(Constant.NSPOSR_URL + "nsposr/B1005", jsonData, checkValue, traceNo);
        HuiFuBasicPayRes res = JSON.parseObject(resultStr, HuiFuBasicPayRes.class);
        if (res.getRespCode().equals("000000")) {
            HuiFuMicropayRes micropayRes = JSON.parseObject(res.getJsonData(), HuiFuMicropayRes.class);
            result.setResultCode("0");
            result.setStatus("0");
            result.setMchId(micropayRes.getMemberId());
            result.setTimeEnd(micropayRes.getEndTime());
            result.setTradeType(dealPayType(micropayRes.getPayChannelType()));
            result.setTotalFee(Integer.valueOf(micropayRes.getOrdAmt()));
            result.setOutTradeNo(micropayRes.getTermOrdId());
        } else if (res.getRespCode().equals("000199")) {
            result.setStatus("1");
            result.setResultCode("1");
            result.setNeedQuery("Y");
        } else {
            result.setStatus("1");
            result.setResultCode("1");
            result.setNeedQuery("N");
        }
        return result;
    }

    public AllPayBaseQueryResult huiFuQuery(String orderId, StorePay storePay) {
        Order order = orderDao.findOne(orderId);
        HuiFuQueryPayReq req = new HuiFuQueryPayReq();
        AllPayBaseQueryResult result = new AllPayBaseQueryResult();
        req.setTermOrdId(orderId);
        req.setMemberId(storePay.getMchId());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        req.setTransDate(sdf.format(order.getAddTime()));

        String traceNo = UUID.randomUUID().toString();

        String jsonData = dealQueryData(req);

        String checkValue = SignUtil.getInstance().signByCFCA(jsonData);

        String resultStr = HttpClient.getInstance().send(Constant.QRCP_URL + "P3009", jsonData, checkValue, traceNo);

        HuiFuBasicPayRes res = JSON.parseObject(resultStr, HuiFuBasicPayRes.class);
        HuiFuQueryPayRes queryPayRes = JSON.parseObject(res.getJsonData(), HuiFuQueryPayRes.class);
        switch (queryPayRes.getTransStat()) {
            case "S":
                result.setTradeState("SUCCESS");
                result.setTradeType(dealPayType(queryPayRes.getPayType()));
                result.setTimeEnd(queryPayRes.getTransDate() + queryPayRes.getTransTime());
                result.setTotalFee(Integer.valueOf(queryPayRes.getTransAmt()));
                result.setOutTradeNo(queryPayRes.getTermOrdId());
                break;
            case "F":
                result.setTradeState("PAYERROR");
                break;
        }
        return result;
    }


    public AllPayJsPayResult huifuJsPay(StorePay storePay, String orderId, String openId) throws Exception {
        return (AllPayJsPayResult) redisSyncLocker.idLock(orderId, o -> {
            AllPayJsPayResult result = new AllPayJsPayResult();
            Order order = orderDao.findOne(orderId);
            HuiFuJSPayReq req = new HuiFuJSPayReq(order, storePay, openId);
            req.setGoodsDesc(URLEncoder.encodeUTF8(service.getBody(order)));
            String notifyUrl = dealNotifyUrl(baseURL + "/v1/pay/huifu/callBack");
            req.setMerPriv(notifyUrl);
            String jsonData = dealJsData(req);
            String checkValue = SignUtil.getInstance().signByCFCA(jsonData);
            String traceNo = UUID.randomUUID().toString().replaceAll("-", "");
            String resultStr = HttpClient.getInstance().send(Constant.NSPOSR_URL + "qrcp/E1113", jsonData, checkValue, traceNo);
            HuiFuBasicPayRes res = JSON.parseObject(resultStr, HuiFuBasicPayRes.class);
            if (res.getRespCode().equals("000000")) {
                HuiFuJSPayRes micropayRes = JSON.parseObject(res.getJsonData(), HuiFuJSPayRes.class);
                result.setResultCode("0");
                result.setStatus("0");
                HuiFuJsPayInfoRes jsPayInfoRes = JSON.parseObject(micropayRes.getPayInfo(), HuiFuJsPayInfoRes.class);
                result.setPayInfo(deal(jsPayInfoRes));
            } else if (res.getRespCode().equals("000199")) {
                result.setStatus("1");
                result.setResultCode("1");
                result.setErrMsg("交易处理中");
            } else {
                result.setStatus("1");
                result.setResultCode("1");
                result.setErrMsg("支付失败，请刷新页面进行重试");
            }
            return result;
        });
    }


    public String dealNotifyUrl(String url) {
        HashMap<String, String> jsonDataMap = new HashMap<String, String>();
        jsonDataMap.put("merNoticeUrl", url);
        return JSON.toJSONString(jsonDataMap);
    }


    public String deal(HuiFuJsPayInfoRes res) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("appId", res.getAppId());
        jsonObject.put("callback_url", "https://admin.huoxingy.com/static/sucPay/index.html");
        jsonObject.put("nonceStr", res.getNonceStr());
        jsonObject.put("package", res.getPack());
        jsonObject.put("paySign", res.getPaySign());
        jsonObject.put("signType", res.getSignType());
        jsonObject.put("timeStamp", res.getTimeStamp());
        jsonObject.put("status", "0");
        return jsonObject.toJSONString();
    }

    public SwiftPassRefundResult huifuRefund(Order order, StorePay storePay) throws Exception {
        SwiftPassRefundResult result = new SwiftPassRefundResult();
        HuiFuRefundPayReq req = new HuiFuRefundPayReq(order, storePay);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        req.setTransDate(sdf.format(order.getAddTime()));
        String jsonData = dealRefundData(req);
        String checkValue = SignUtil.getInstance().signByCFCA(jsonData);
        String traceNo = UUID.randomUUID().toString().replaceAll("-", "");
        String resultStr = HttpClient.getInstance().send(Constant.NSPOSR_URL + "refund/E1115", jsonData, checkValue, traceNo);
        HuiFuBasicPayRes res = JSON.parseObject(resultStr, HuiFuBasicPayRes.class);
        if (res.getRespCode().equals("000000")) {
            HuiFuRefundPayRes micropayRes = JSON.parseObject(res.getJsonData(), HuiFuRefundPayRes.class);
            switch (micropayRes.getRefundStat()) {
                case "S":
                    result.setResultCode("0");
                    result.setStatus("0");
                    result.setRefundId(micropayRes.getTermOrdId());
                    result.setRefundFee(Integer.valueOf(micropayRes.getRefundAmt()));
                    break;
            }
        } else if (res.getRespCode().equals("000199")) {
            result.setStatus("1");
            result.setResultCode("1");
            result.setErrMsg("交易处理中");
        } else {
            result.setStatus("1");
            result.setResultCode("1");
            result.setErrMsg("退款失败，请联系商家");
        }
        return result;
    }

    public AllPayReverseResult cancelPay(String orderId) {
        Order order = orderDao.findOne(orderId);
        Reward reward = rewardDao.findOne(orderId);

        log.info("门店{}, 订单号{}, 操作{}, 操作内容{}, reward:{}", order.getStoreId(), order.getId(), "取消订单开始", order, reward);

        if (reward != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            String date = sdf.format(order.getAddTime());
            reward.setPayChannel(OrderPayChannel.HUI_FU);
            if (reward.getStatus().equals(OrderStatus.CANCELED)) {
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "该笔支付已经被取消");
                throw new RuntimeException("该笔支付已经被取消");
            } else if (reward.getStatus().equals(OrderStatus.UNFINISHED) || reward.getStatus().equals(OrderStatus.FINISHED)) {
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "已经成功支付，取消支付操作被中止。");
                throw new RuntimeException("已经成功支付，取消支付操作被中止。");
            } else {
                StorePay store = storePayDao.findByStoreIdAndStartEnabled("574b59ef-b19c-11e7-9233-37891743d141", true);
                AllPayBaseQueryResult paymentResult = huiFuQuery(reward.getId(), store);
                if (paymentResult.isSuccess()) {
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "已经成功支付，取消支付操作被中止(火星云)。");
                    throw new RuntimeException("已经成功支付，取消支付操作被中止。");
                }
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "优先调用撤消订单接口");
                AllPayReverseResult result = huifuCancelPay(store.getMchId(), reward.getId(), date);
                if (result.isSuccess()) {
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            reward.setStatus(OrderStatus.CANCELED);
                            rewardDao.save(reward);
                        }
                    });
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "撤消成功");
                    return result;
                } else {
                    throw new RuntimeException(result.getErrMsg());
                }
            }
        } else {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            String date = sdf.format(order.getAddTime());
            if (order.getStatus().equals(OrderStatus.CANCELED)) {
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "支付已经被取消，请到订单列表查询确认");
                throw new RuntimeException("支付已经被取消，请到订单列表查询确认");
            } else if (order.getStatus().equals(OrderStatus.UNFINISHED) || order.getStatus().equals(OrderStatus.FINISHED)) {
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "订单已经成功支付，取消支付操作被中止。请到订单列表查询确认");
                throw new RuntimeException("订单已经成功支付，取消支付操作被中止。请到订单列表查询确认");
            } else {
                StorePay store = storePayDao.findByStoreIdAndStartEnabled(order.getStoreId(), true);
                AllPayBaseQueryResult paymentResult = huiFuQuery(order.getId(), store);
                order.setPayChannel(OrderPayChannel.HUI_FU);
                if (paymentResult.isSuccess()) {
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "订单已经成功支付，取消支付操作被中止。请到订单列表查询确认");
                    throw new RuntimeException("订单已经成功支付，取消支付操作被中止。请到订单列表查询确认");
                }
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "优先调用撤消订单接口");
                // 先调用撤销订单接口
                AllPayReverseResult result = huifuCancelPay(store.getMchId(), reward.getId(), date);
                if (result.isSuccess()) {
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            order.setStatus(OrderStatus.CANCELED);
                            orderDao.save(order);
                        }
                    });
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "撤消成功");
                    return result;
                } else {
                    throw new RuntimeException(result.getErrMsg());
                }
            }
        }
    }

    public AllPayReverseResult huifuCancelPay(String mchId, String id, String date) {
        HuiFUCancelPayReq req = new HuiFUCancelPayReq();
        AllPayReverseResult result = new AllPayReverseResult();
        req.setMemberId(mchId);
        req.setTermOrdId(id);
        req.setTransDate(date);
        String jsonData = dealCancelData(req);
        String checkValue = SignUtil.getInstance().signByCFCA(jsonData);
        String traceNo = UUID.randomUUID().toString().replaceAll("-", "");
        String resultStr = HttpClient.getInstance().send(Constant.NSPOSR_URL + "qrcp/refundQuery", jsonData, checkValue, traceNo);
        HuiFuBasicPayRes res = JSON.parseObject(resultStr, HuiFuBasicPayRes.class);
        if (res.getRespCode().equals("000000")) {
            HuiFuRefundQueryRes micropayRes = JSON.parseObject(res.getJsonData(), HuiFuRefundQueryRes.class);
            switch (micropayRes.getRefundStat()) {
                case "S":
                    result.setResultCode("0");
                    result.setStatus("0");
                    break;
                case "P":
                    result.setStatus("1");
                    result.setResultCode("1");
                    break;
            }

        } else if (res.getRespCode().equals("000199")) {
            result.setStatus("1");
            result.setResultCode("1");
            result.setErrMsg("交易处理中");
        } else {
            result.setStatus("1");
            result.setResultCode("1");
            result.setErrMsg("退款失败，请联系商家");
        }
        return result;
    }


    public AllPayRefundQueryResult huifuRefundQuery(StorePay storePay, Order order) throws Exception {
        AllPayRefundQueryResult result = new AllPayRefundQueryResult();
        HuiFuRefundQueryReq req = new HuiFuRefundQueryReq(order, storePay);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        req.setTransDate(sdf.format(order.getAddTime()));
        String jsonData = dealRefundQueryData(req);
        String checkValue = SignUtil.getInstance().signByCFCA(jsonData);
        String traceNo = UUID.randomUUID().toString().replaceAll("-", "");
        String resultStr = HttpClient.getInstance().send(Constant.NSPOSR_URL + "qrcp/refundQuery", jsonData, checkValue, traceNo);
        HuiFuBasicPayRes res = JSON.parseObject(resultStr, HuiFuBasicPayRes.class);
        if (res.getRespCode().equals("000000")) {
            HuiFuRefundQueryRes micropayRes = JSON.parseObject(res.getJsonData(), HuiFuRefundQueryRes.class);
            switch (micropayRes.getRefundStat()) {
                case "S":
                    result.setResultCode("0");
                    result.setStatus("0");
                    result.setRefundId(micropayRes.getTermOrdId());
                    result.setRefundFee(Integer.valueOf(micropayRes.getRefundAmt()));
                    result.setRefundTime(micropayRes.getTransDate() + micropayRes.getTransTime());
                    result.setRefundStatus("SUCCESS");
                    break;
                case "P":
                    result.setStatus("0");
                    result.setResultCode("0");
                    result.setRefundStatus("PROCESSING");
                    break;
            }

        } else if (res.getRespCode().equals("000199")) {
            result.setStatus("1");
            result.setResultCode("1");
            result.setErrMsg("交易处理中");
        } else {
            result.setStatus("1");
            result.setResultCode("1");
            result.setErrMsg("退款失败，请联系商家");
        }
        return result;
    }

    public ALLPayQrCodeResult huifuRewardQrCode(StorePay storePay, Reward reward, PayTypeEnum payType) throws Exception {
        return (ALLPayQrCodeResult) redisSyncLocker.idLock(reward.getId(), new ISyncExecutor() {
            @Override
            public Object execute(Object o) throws Exception {
                ALLPayQrCodeResult result = new ALLPayQrCodeResult();
                HuiFuQRCodeReq req = new HuiFuQRCodeReq(storePay, reward);
                if (payType.equals(PayTypeEnum.PAY_WX_NATIVE)) {
                    req.setPayChannelType("W1");
                    req.setAppId("wxf6f45bc02f8e7de8");
                } else {
                    req.setPayChannelType("W2");
                }
                String notifyUrl = dealNotifyUrl(baseURL + "/v1/pay/huifu/callBack");
                req.setMerPriv(notifyUrl);
                req.setGoodsDesc(service.getRewardBody(reward));
                String jsonData = dealQrCodeQueryData(req);
                String checkValue = SignUtil.getInstance().signByCFCA(jsonData);
                String traceNo = UUID.randomUUID().toString().replaceAll("-", "");
                String resultStr = HttpClient.getInstance().send(Constant.NSPOSR_URL + "qrcp/E1103", jsonData, checkValue, traceNo);
                HuiFuBasicPayRes res = JSON.parseObject(resultStr, HuiFuBasicPayRes.class);
                if (res.getRespCode().equals("000000")) {
                    HuiFuQRCodeRes micropayRes = JSON.parseObject(res.getJsonData(), HuiFuQRCodeRes.class);
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            reward.setPayChannel(OrderPayChannel.HUI_FU);
                            reward.setStatus(OrderStatus.NOTSURE);
                            rewardDao.save(reward);
                        }
                    });
                    result.setStatus("0");
                    result.setResultCode("0");
                    result.setCodeImgURL(micropayRes.getQrcodeUrl());
                } else if (res.getRespCode().equals("000199")) {
                    result.setStatus("1");
                    result.setResultCode("1");
                    result.setErrMsg("交易处理中");
                } else {
                    result.setStatus("1");
                    result.setResultCode("1");
                    reward.setStatus(OrderStatus.CANCELED);
                    result.setErrMsg("获取二维码失败，请联系商家");
                }
                return result;
            }
        });
    }


    public ALLPayQrCodeResult huifuQRCode(StorePay storePay, Order order, PayTypeEnum payType) throws Exception {
        return (ALLPayQrCodeResult) redisSyncLocker.idLock(order.getId(), new ISyncExecutor() {
            @Override
            public Object execute(Object o) throws Exception {
                ALLPayQrCodeResult result = new ALLPayQrCodeResult();
                HuiFuQRCodeReq req = new HuiFuQRCodeReq(storePay, order);
                if (payType.equals(PayTypeEnum.PAY_WX_NATIVE)) {
                    req.setPayChannelType("W1");
                    req.setAppId("wxf6f45bc02f8e7de8");
                } else {
                    req.setPayChannelType("W2");
                }
                req.setGoodsDesc(service.getBody(order));
                String jsonData = dealQrCodeQueryData(req);
                String checkValue = SignUtil.getInstance().signByCFCA(jsonData);
                String traceNo = UUID.randomUUID().toString().replaceAll("-", "");
                String resultStr = HttpClient.getInstance().send(Constant.NSPOSR_URL + "qrcp/E1103", jsonData, checkValue, traceNo);
                HuiFuBasicPayRes res = JSON.parseObject(resultStr, HuiFuBasicPayRes.class);
                if (res.getRespCode().equals("000000")) {
                    HuiFuQRCodeRes micropayRes = JSON.parseObject(res.getJsonData(), HuiFuQRCodeRes.class);
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            order.setPayChannel(OrderPayChannel.HUI_FU);
                            order.setStatus(OrderStatus.NOTSURE);
                            orderDao.save(order);
                        }
                    });
                    result.setStatus("0");
                    result.setResultCode("0");
                    result.setCodeImgURL(micropayRes.getQrcodeUrl());
                } else if (res.getRespCode().equals("000199")) {
                    result.setStatus("1");
                    result.setResultCode("1");
                    result.setErrMsg("交易处理中");
                } else {
                    result.setStatus("1");
                    result.setResultCode("1");
                    order.setStatus(OrderStatus.CANCELED);
                    result.setErrMsg("获取二维码失败，请联系商家");
                }
                return result;
            }
        });
    }

    public void huifuCallbackForMicroPaymentFailed(String orderId, AllPayBaseQueryResult queryResult) throws Exception {
        Order order = orderDao.findOne(orderId);
        Reward reward = rewardDao.findOne(orderId);
        if (reward != null) {
            if (reward.getStatus().equals(OrderStatus.INIT)) {
                // 说明已经处理过支付失败的情况
                return ;
            } else {
                // 支付失败后订单返回未结算状态，允许再次结算
                reward.setStatus(OrderStatus.INIT);
                transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                    @Override
                    protected void doInTransactionWithoutResult(TransactionStatus status) {
                        rewardDao.save(reward);
                    }
                });
            }
        } else {
            if (order.getStatus().equals(OrderStatus.CANCELED)) {
                // 说明已经处理过支付失败的情况
                return ;
            } else {
                // 支付失败后订单返回未结算状态，允许再次结算
                order.setStatus(OrderStatus.CANCELED);

                transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                    @Override
                    protected void doInTransactionWithoutResult(TransactionStatus status) {
                        orderDao.save(order);
                    }
                });
            }
        }
    }

    public void huifuCallbackForMicroPaymentSuccess(AllPayBaseQueryResult queryResult) throws Exception {
        Order order = orderDao.findOne(queryResult.getOutTradeNo());
        Reward reward = rewardDao.findOne(queryResult.getOutTradeNo());
        if (reward != null) {
            reward.setPayChannel(OrderPayChannel.SAO_BEI);
            if (reward.getStatus().equals(OrderStatus.FINISHED) || reward.getStatus().equals(OrderStatus.UNFINISHED)) {
                // 已经处理过支付成功事件
                return;
            }
            reward.setPaymentTime(MyDateUtils.getDateFormatDd(queryResult.getTimeEnd(), "yyyyMMddHHmmss"));
            reward.setChannel(queryResult.getTradeType());
            reward.setStatus(OrderStatus.FINISHED);
            AccountBalance accountBalance = accountBalanceDao.findByStoreId(reward.getStoreId());
            log.info("accountBalance" + accountBalance);
            if (accountBalance == null) {
                accountBalance = new AccountBalance(queryResult.getTotalFee() / 100.0, reward.getStoreId());
            } else {
                accountBalance.setAmount(accountBalance.getAmount() + queryResult.getTotalFee() / 100.0);
            }
            // 订单与支付信息的更新在同一个事务中
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    rewardDao.save(reward);

                }
            });
            accountBalanceDao.save(accountBalance);
            aliyunMNSSend.sendClint(reward.getId());
        } else {
            if (order.getStatus().equals(OrderStatus.FINISHED) || order.getStatus().equals(OrderStatus.UNFINISHED)) {
                // 已经处理过支付成功事件
                return;
            }
            order.setPayChannel(OrderPayChannel.SAO_BEI);
            Store store = storeDao.findOne(order.getStoreId());

            Payment payment = new Payment();
            payment.setId(UuidUtil.getUuid());
            payment.setOrderId(queryResult.getOutTradeNo());
            payment.setStoreId(order.getStoreId());
            payment.setSuccess(queryResult.isSuccess());
            payment.setStatus(PaymentStatus.SUCCESS);
            Date paymentTime = MyDateUtils.getDateFormatDd(queryResult.getTimeEnd(), "yyyyMMddHHmmss");
            payment.setCreateTime(paymentTime);
            payment.setAmount(queryResult.getTotalFee() / 100.0);
            payment.setChannel(queryResult.getTradeType());


            if (OrderSource.POS == order.getSource()) {
                order.setStatus(OrderStatus.FINISHED);
            } else {
                order.setStatus(OrderStatus.UNFINISHED);
            }
            order.setPaymentTime(payment.getCreateTime());
            order.setPayId(payment.getId());
            order.setChannel(queryResult.getTradeType());

            // 订单与支付信息的更新在同一个事务中
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    paymentDao.save(payment);
                    orderDao.save(order);
                }
            });

            service.postPaymentSuccess(order, store);
        }
    }

    public void callbackForThirdPartyRefundFail(AllPayRefundQueryResult result) {
        Order refundOrder = orderDao.findOne(result.getOutRefundNo());
        refundOrder.setStatus(OrderStatus.INIT);
        refundOrder.setPayChannel(OrderPayChannel.HUI_FU);
        transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                orderDao.save(refundOrder);
            }
        });
    }


    public void callbackForThirdPartyRefundSuccess(AllPayRefundQueryResult result) {
        log.debug("Step in callback for third party refund success...");
        Payment payment = paymentDao.findOne(result.getRefundId());
        payment.setStatus(PaymentStatus.SUCCESS);
        payment.setSuccess(true);

        Date paymentTime = MyDateUtils.getDateFormatDd(result.getRefundTime(), "yyyyMMddHHmmss");
        payment.setCreateTime(paymentTime);

        Order refundOrder = orderDao.findOne(payment.getOrderId());
        refundOrder.setPayChannel(OrderPayChannel.HUI_FU);
        refundOrder.setStatus(OrderStatus.REFUNDED);
        refundOrder.setPaymentTime(paymentTime);

        transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                orderDao.save(refundOrder);
                paymentDao.save(payment);
            }
        });

        try {
            service.postRefundSuccess(refundOrder);
        } catch (Exception e1) {
            log.info(e1.toString());
        }
    }

    public String dealRefundQueryData(HuiFuRefundQueryReq req) {
        HashMap<String, String> jsonDataMap = new HashMap<String, String>();
        jsonDataMap.put("termOrdId", req.getTermOrdId());
        jsonDataMap.put("memberId", req.getMemberId());
        jsonDataMap.put("transDate", req.getTermOrdId());
        jsonDataMap.put("apiVersion", req.getApiVersion());
        return JSON.toJSONString(jsonDataMap);
    }

    public String dealCancelData(HuiFUCancelPayReq req) {
        HashMap<String, String> jsonDataMap = new HashMap<String, String>();
        jsonDataMap.put("termOrdId", req.getTermOrdId());
        jsonDataMap.put("memberId", req.getMemberId());
        jsonDataMap.put("transDate", req.getTermOrdId());
        jsonDataMap.put("apiVersion", req.getApiVersion());
        return JSON.toJSONString(jsonDataMap);
    }

    public String dealQrCodeQueryData(HuiFuQRCodeReq req) {
        HashMap<String, String> jsonDataMap = new HashMap<String, String>();
        jsonDataMap.put("termOrdId", req.getTermOrdId());
        jsonDataMap.put("goodsDesc", req.getMemberId());
        jsonDataMap.put("memberId", req.getTermOrdId());
        jsonDataMap.put("ordAmt", req.getApiVersion());
        jsonDataMap.put("apiVersion", req.getTermOrdId());
        jsonDataMap.put("payChannelType", req.getMemberId());
        return JSON.toJSONString(jsonDataMap);
    }

    public String dealQueryData(HuiFuQueryPayReq req) {
        HashMap<String, String> jsonDataMap = new HashMap<String, String>();
        jsonDataMap.put("ordType", req.getOrdType());
        jsonDataMap.put("memberId", req.getMemberId());
        jsonDataMap.put("termOrdId", req.getTermOrdId());
        jsonDataMap.put("transDate", req.getTransDate());
        jsonDataMap.put("apiVersion", req.getApiVersion());
        return JSON.toJSONString(jsonDataMap);
    }

    public String dealRefundData(HuiFuRefundPayReq req) {
        HashMap<String, String> jsonDataMap = new HashMap<String, String>();
        jsonDataMap.put("termOrdId", req.getTermOrdId());
        jsonDataMap.put("memberId", req.getMemberId());
        jsonDataMap.put("transDate", req.getTransDate());
        jsonDataMap.put("apiVersion", req.getApiVersion());
        jsonDataMap.put("ordAmt", req.getOrdAmt());
        return JSON.toJSONString(jsonDataMap);
    }


    public String dealJsData(HuiFuJSPayReq req) {
        HashMap<String, String> jsonDataMap = new HashMap<String, String>();
        jsonDataMap.put("ordAmt", req.getOrdAmt());
        jsonDataMap.put("apiVersion", req.getApiVersion());
        jsonDataMap.put("payChannelType", req.getPayChannelType());
        jsonDataMap.put("payChannelId", req.getPayChannelId());
        jsonDataMap.put("payScene", req.getPayScene());
        jsonDataMap.put("appId", req.getAppId());
        jsonDataMap.put("openId", req.getOpenId());
        jsonDataMap.put("clientIp", req.getClientIp()); //二维码正向交易时与termOrdId、outTransId中有一个必填
        jsonDataMap.put("termOrdId", req.getTermOrdId());
        jsonDataMap.put("goodsDesc", req.getGoodsDesc());
        jsonDataMap.put("memberId", req.getMemberId());
        return JSON.toJSONString(jsonDataMap);
    }

    public String dealHuiFuMicroPay(HuiFuMicroPayReq req) throws Exception {
        HashMap<String, String> jsonDataMap = new HashMap<String, String>();
        jsonDataMap.put("termOrdId", req.getTermOrdId());
        jsonDataMap.put("memberId", req.getMemberId());
        jsonDataMap.put("ordAmt", req.getOrdAmt());
        jsonDataMap.put("authCode", req.getAuthCode());//二维码
        jsonDataMap.put("goodsDesc", URLEncoder.encode(req.getGoodsDesc(), "utf-8"));
        jsonDataMap.put("apiVersion", req.getApiVersion());
        return JSON.toJSONString(jsonDataMap);
    }


    private String dealPayType(String type) {
        String payType = "";
        switch (type) {
            case "W":
                payType = "pay.wechat.native";
                break;
            case "A":
                payType = "pay.alipay.native";
                break;
            case "U":
                payType = "pay.unionpay.micropay";
                break;
        }
        return payType;

    }


}
